<!DOCTYPE html>
<html lang="en">
<head>
        <meta charset="utf-8" />
        <title>Part.3.B.5.bnf-ebnf-pebnf</title>
        <link rel="stylesheet" href="/theme/css/main.css" />

        <!--[if IE]>
            <script src="http://html5shiv.googlecode.com/svn/trunk/html5.js"></script>
        <![endif]-->
</head>

<body id="index" class="home">
        <header id="banner" class="body">
                <h1><a href="/">PythonTutorials </a></h1>
                <nav><ul>
                    <li><a href="/category/cpp.html">cpp</a></li>
                    <li class="active"><a href="/category/python.html">python</a></li>
                </ul>
                </nav>
        </header><!-- /#banner -->
<section id="content" class="body">
  <article>
    <header>
      <h1 class="entry-title">
        <a href="/Part.3.B.5.bnf-ebnf-pebnf.html" rel="bookmark"
           title="Permalink to Part.3.B.5.bnf-ebnf-pebnf">Part.3.B.5.bnf-ebnf-pebnf</a></h1>
    </header>

    <div class="entry-content">
<footer class="post-info">
        <span>Mon 06 April 2020</span>
<span>| tags: <a href="/tag/python.html">python</a><a href="/tag/progarmming.html">progarmming</a><a href="/tag/excel.html">Excel</a></span>
</footer><!-- /.post-info -->      <h1>BNF 以及 EBNF</h1>
<p>通常情况下，你很少会在入门书籍里读到关于 Backus-Naur Form（BNF，巴科斯-诺尔范式）和 Extended Backus-Naur Form（EBNF）的话题 —— 它们都被普遍认为是 “非专业人士无需了解的话题”，隐含的另外一层含义是 “反正就算给他们讲他们也无论如何看不懂”……</p>
<p>然而，在我眼里，这事非讲不可 —— 这是这本 “书” 的设计目标决定的。</p>
<p>严格意义上来讲，在《自学是门手艺》中，以自学编程为例，我完全没必要自己动手耗时费力写那么多东西 —— 如果仅仅是为了让读者 “入门” 的话。编程入门书籍，或者 Python 编程入门书籍，都已经太多太多了，其中质量过硬的书籍也多得去了 —— 并且，如果你没有英文阅读障碍，那你就会发现网上有太多非常优质的免费教程…… 真的轮不到李笑来同学再写一次。</p>
<p>我写这本书的目标是：</p>
<blockquote>
<p>让读者从认知自学能力开始，通过自学编程作为第一个实践，逐步完整掌握自学能力，进而在随后漫长的人生中，需要什么就去学什么，</p>
</blockquote>
<p>…… 不用非得找人教、找人带 —— 只有这样，<strong>前途</strong>这两个字才会变得实在。</p>
<p>于是，我最希望能做到的是，从这里了解了自学方法论，也了解了编程以及 Python 编程的基础概念之后，《自学是门手艺》的读者能够<strong>自顾自地踏上征程，一路走下去</strong> —— 至于走到哪里，能走到哪里，不是我一个作者一厢情愿能够决定的，是吧？</p>
<p>当然，会自学的人运气一定不会差。</p>
<p>于是，这本 “书” 的核心目标之一，换个说法就是：</p>
<blockquote>
<p>我希望读者在读完《自学是门手艺》之后，有能力独立地去全面研读<a href="https://docs.python.org/3/">官方文档</a> —— 甚至是各种编程语言、各种软件的相关的文档（包括它们的官方文档）。</p>
</blockquote>
<p>自学编程，很像独自一人冲入了一个丛林，里面什么动物都有…… 而且那个丛林很大很大，虽然丛林里有的地方很美，可若是没有地图和指南针，你就会迷失方向。</p>
<p>其实吧，地图也不是没有 —— 别说 Python 了，无论什么编程语言（包括无论什么软件）都有很翔实的官方文档…… 可是吧，绝大多数人无论买多少书、上多少课，就是不去用官方 “地图”，就不！</p>
<p>—— 其实倒不是说 “第三方地图” 更好，实际的原因很不好意思说出来：</p>
<blockquote>
<ul>
<li>这首先吧，觉得官方文档阅读量太大了……（嗯？那地图不是越详细越好吗？）</li>
<li>那还有吧…… 也不是没去看过，<strong>看不懂</strong>……（嗯…… 这对初学者倒是个问题！）</li>
</ul>
</blockquote>
<p>所以，我要认为这本 “书” 的最重要工作是：</p>
<blockquote>
<p>为读者解读清楚地图上的 “图例”，从此之后读者在任何需要的时候能够彻底读懂地图。</p>
</blockquote>
<p>在阅读官方文档的时候，很多人在 <a href="https://docs.python.org/3/tutorial/index.html">The Python Tutorial</a> 上就已经觉得吃力了…… 如果到了 <a href="https://docs.python.org/3/library/index.html">Standard Libraries</a> 和 <a href="https://docs.python.org/3/reference/index.html">Language References</a> 的部分，就基本上完全放弃了，比如，以下这段摘自 <a href="https://docs.python.org/3/library/string.html">string —— Common string operations</a>：</p>
<blockquote>
<p>Format Specification Mini-Language
...
The general form of a standard format specifier is:</p>
</blockquote>
<div class="highlight"><pre><span></span>format_spec     ::=  [[fill]align][sign][#][0][width][grouping_option][.precision][type]
fill            ::=  &lt;any character&gt;
align           ::=  &quot;&lt;&quot; | &quot;&gt;&quot; | &quot;=&quot; | &quot;^&quot;
sign            ::=  &quot;+&quot; | &quot;-&quot; | &quot; &quot;
width           ::=  digit+
grouping_option ::=  &quot;_&quot; | &quot;,&quot;
precision       ::=  digit+
type            ::=  &quot;b&quot; | &quot;c&quot; | &quot;d&quot; | &quot;e&quot; | &quot;E&quot; | &quot;f&quot; | &quot;F&quot; | &quot;g&quot; | &quot;G&quot; |
                     &quot;n&quot; | &quot;o&quot; | &quot;s&quot; | &quot;x&quot; | &quot;X&quot; | &quot;%&quot;
</pre></div>


<blockquote>
<p>...</p>
</blockquote>
<p>读到这，看着一大堆的 <code>::=</code> <code>[]</code> <code>|</code> 当场傻眼了……</p>
<p>这是 BNF 描述，还是 Python 自己定制的 EBNF…… 为了理解它们，以后当然最好有空研究一下 “上下文无关文法”（<a href="https://en.wikipedia.org/wiki/Context-free_grammar">Context-free Grammar</a>），没准未来你一高兴就会去玩一般人不敢玩的各种 Parser，甚至干脆自己写门编程语言啥的…… 不过，完全可以跳过那些复杂的东西的 —— 因为你当前的目标只不过是 “能够读懂那些符号的含义”。</p>
<p>其实吧，真的不难的 —— 它就是语法描述的方法。</p>
<p>比如，什么是符合语法的整数（Integer）呢？符合以下语法描述的是整数（使用 Python 的 EBNF）：</p>
<div class="highlight"><pre><span></span>integer ::= [sign] digit +
sign    ::= &quot;+&quot; | &quot;-&quot;
digit   ::=  &quot;0&quot; | &quot;1&quot; | &quot;2&quot; | &quot;3&quot; | &quot;4&quot; | &quot;5&quot; | &quot;6&quot; | &quot;7&quot; | &quot;8&quot; | &quot;9&quot;
</pre></div>


<p>以上的描述中，基本符号没几个，它们各自的含义是：</p>
<blockquote>
<ul>
<li><code>::=</code> 表示定义；</li>
<li><code>&lt; &gt;</code> 尖括号里的内容表示必选内容；</li>
<li><code>[ ]</code> 中是可选项；</li>
<li><code>" "</code> 双引号里的内容表示字符；</li>
<li><code>|</code> 竖线两边的是可选内容，相当于or；</li>
<li><code>*</code> 表示零个或者多个……</li>
<li><code>+</code> 表示一个或者多个……</li>
</ul>
</blockquote>
<p>于是：</p>
<blockquote>
<ol>
<li><code>interger</code> 定义是：由 “可选的 <code>sign</code>” 和 “一个或者多个 <code>digit</code> 的集合” 构成 —— 第一行末尾那个 <code>+</code> 的作用和正则表达式里的 <code>+</code> 一样；</li>
<li><code>sign</code> 的定义是什么呢？要么是 <code>+</code> 要么是 <code>-；</code></li>
<li><code>digit</code> 的定义是什么呢？从 <code>"0"</code> 到 <code>"9"</code> 中的任何一个值……</li>
</ol>
</blockquote>
<p>于是，<code>99</code>、<code>+99</code>、<code>-99</code>，都是符合以上语法描述的 <code>integer</code>；但 <code>99+</code> 和 <code>99-</code> 肯定不符合以上语法描述的 <code>integer</code>。</p>
<p>很简单吧？反正就是在 <code>::=</code> 左边逐行列出一个语法构成的所有要素，而后在右边逐行逐一定义，直至全部要素定义完毕。</p>
<p>也许那些在此之前已经熟悉 BNF 范式的人会有点惊讶，“你怎么连 ‘<em>终结符</em>’ 和 ‘<em>非终结符</em>’ 这种最基本的概念都跳过了？” —— 是呀，即便不讲那俩概念也能把这事讲清楚到 “能马上开始用” 了的地步…… 这就是我经常说的，“人类有这个神奇的本领，擅长使用自己并不懂的东西……”</p>
<p>Python 对 BNF 的拓展，借鉴了正则表达式<a href='#fn1' name='fn1b'><sup>[1]</sup></a> —— 从最后两个符号的使用（<code>*</code> <code>+</code>）你可以看得出来。顺带说，这也是为什么这本 “书” 里非要讲其他入门书籍里不讲的正则表达式的原因之一。</p>
<p>又由于 Python 的社区文档是二十来年长期积累的，有时标注方法并不一致。比如，在描述 <a href="https://docs.python.org/3/reference/grammar.html">Python Full Grammar specification</a> 的时候，他们用的语法标注符号体系就跟上面描述 String 的语法不一样了，是这样的：</p>
<blockquote>
<ul>
<li><code>:</code> 表示定义；</li>
<li><code>[ ]</code> 中是可选项；</li>
<li><code>' '</code> 引号里的内容表示字符；</li>
<li><code>|</code> 竖线两边的是可选内容，相当于or；</li>
<li><code>*</code> 表示零个或者多个……</li>
<li><code>+</code> 表示一个或者多个……</li>
</ul>
</blockquote>
<p>—— 用冒号 <code>:</code> 替代了 <code>::=</code>，用单引号 <code>''</code> 替代了双引号 <code>""</code>，而尖括号 <code>&lt;&gt;</code> 干脆不用了：</p>
<div class="highlight"><pre><span></span><span class="c1"># Grammar for Python</span>

<span class="c1"># NOTE WELL: You should also follow all the steps listed at</span>
<span class="c1"># https://devguide.python.org/grammar/</span>

<span class="c1"># Start symbols for the grammar:</span>
<span class="c1">#       single_input is a single interactive statement;</span>
<span class="c1">#       file_input is a module or sequence of commands read from an input file;</span>
<span class="c1">#       eval_input is the input for the eval() functions.</span>
<span class="c1"># NB: compound_stmt in single_input is followed by extra NEWLINE!</span>
<span class="n">single_input</span><span class="p">:</span> <span class="n">NEWLINE</span> <span class="o">|</span> <span class="n">simple_stmt</span> <span class="o">|</span> <span class="n">compound_stmt</span> <span class="n">NEWLINE</span>
<span class="n">file_input</span><span class="p">:</span> <span class="p">(</span><span class="n">NEWLINE</span> <span class="o">|</span> <span class="n">stmt</span><span class="p">)</span><span class="o">*</span> <span class="n">ENDMARKER</span>
<span class="n">eval_input</span><span class="p">:</span> <span class="n">testlist</span> <span class="n">NEWLINE</span><span class="o">*</span> <span class="n">ENDMARKER</span>

<span class="n">decorator</span><span class="p">:</span> <span class="s1">&#39;@&#39;</span> <span class="n">dotted_name</span> <span class="p">[</span> <span class="s1">&#39;(&#39;</span> <span class="p">[</span><span class="n">arglist</span><span class="p">]</span> <span class="s1">&#39;)&#39;</span> <span class="p">]</span> <span class="n">NEWLINE</span>
<span class="n">decorators</span><span class="p">:</span> <span class="n">decorator</span><span class="o">+</span>
<span class="n">decorated</span><span class="p">:</span> <span class="n">decorators</span> <span class="p">(</span><span class="n">classdef</span> <span class="o">|</span> <span class="n">funcdef</span> <span class="o">|</span> <span class="n">async_funcdef</span><span class="p">)</span>

<span class="n">async_funcdef</span><span class="p">:</span> <span class="s1">&#39;async&#39;</span> <span class="n">funcdef</span>
<span class="n">funcdef</span><span class="p">:</span> <span class="s1">&#39;def&#39;</span> <span class="n">NAME</span> <span class="n">parameters</span> <span class="p">[</span><span class="s1">&#39;-&gt;&#39;</span> <span class="n">test</span><span class="p">]</span> <span class="s1">&#39;:&#39;</span> <span class="n">suite</span>

<span class="n">parameters</span><span class="p">:</span> <span class="s1">&#39;(&#39;</span> <span class="p">[</span><span class="n">typedargslist</span><span class="p">]</span> <span class="s1">&#39;)&#39;</span>
<span class="n">typedargslist</span><span class="p">:</span> <span class="p">(</span><span class="n">tfpdef</span> <span class="p">[</span><span class="s1">&#39;=&#39;</span> <span class="n">test</span><span class="p">]</span> <span class="p">(</span><span class="s1">&#39;,&#39;</span> <span class="n">tfpdef</span> <span class="p">[</span><span class="s1">&#39;=&#39;</span> <span class="n">test</span><span class="p">])</span><span class="o">*</span> <span class="p">[</span><span class="s1">&#39;,&#39;</span> <span class="p">[</span>
        <span class="s1">&#39;*&#39;</span> <span class="p">[</span><span class="n">tfpdef</span><span class="p">]</span> <span class="p">(</span><span class="s1">&#39;,&#39;</span> <span class="n">tfpdef</span> <span class="p">[</span><span class="s1">&#39;=&#39;</span> <span class="n">test</span><span class="p">])</span><span class="o">*</span> <span class="p">[</span><span class="s1">&#39;,&#39;</span> <span class="p">[</span><span class="s1">&#39;**&#39;</span> <span class="n">tfpdef</span> <span class="p">[</span><span class="s1">&#39;,&#39;</span><span class="p">]]]</span>
      <span class="o">|</span> <span class="s1">&#39;**&#39;</span> <span class="n">tfpdef</span> <span class="p">[</span><span class="s1">&#39;,&#39;</span><span class="p">]]]</span>
  <span class="o">|</span> <span class="s1">&#39;*&#39;</span> <span class="p">[</span><span class="n">tfpdef</span><span class="p">]</span> <span class="p">(</span><span class="s1">&#39;,&#39;</span> <span class="n">tfpdef</span> <span class="p">[</span><span class="s1">&#39;=&#39;</span> <span class="n">test</span><span class="p">])</span><span class="o">*</span> <span class="p">[</span><span class="s1">&#39;,&#39;</span> <span class="p">[</span><span class="s1">&#39;**&#39;</span> <span class="n">tfpdef</span> <span class="p">[</span><span class="s1">&#39;,&#39;</span><span class="p">]]]</span>
  <span class="o">|</span> <span class="s1">&#39;**&#39;</span> <span class="n">tfpdef</span> <span class="p">[</span><span class="s1">&#39;,&#39;</span><span class="p">])</span>
<span class="n">tfpdef</span><span class="p">:</span> <span class="n">NAME</span> <span class="p">[</span><span class="s1">&#39;:&#39;</span> <span class="n">test</span><span class="p">]</span>
<span class="n">varargslist</span><span class="p">:</span> <span class="p">(</span><span class="n">vfpdef</span> <span class="p">[</span><span class="s1">&#39;=&#39;</span> <span class="n">test</span><span class="p">]</span> <span class="p">(</span><span class="s1">&#39;,&#39;</span> <span class="n">vfpdef</span> <span class="p">[</span><span class="s1">&#39;=&#39;</span> <span class="n">test</span><span class="p">])</span><span class="o">*</span> <span class="p">[</span><span class="s1">&#39;,&#39;</span> <span class="p">[</span>
        <span class="s1">&#39;*&#39;</span> <span class="p">[</span><span class="n">vfpdef</span><span class="p">]</span> <span class="p">(</span><span class="s1">&#39;,&#39;</span> <span class="n">vfpdef</span> <span class="p">[</span><span class="s1">&#39;=&#39;</span> <span class="n">test</span><span class="p">])</span><span class="o">*</span> <span class="p">[</span><span class="s1">&#39;,&#39;</span> <span class="p">[</span><span class="s1">&#39;**&#39;</span> <span class="n">vfpdef</span> <span class="p">[</span><span class="s1">&#39;,&#39;</span><span class="p">]]]</span>
      <span class="o">|</span> <span class="s1">&#39;**&#39;</span> <span class="n">vfpdef</span> <span class="p">[</span><span class="s1">&#39;,&#39;</span><span class="p">]]]</span>
  <span class="o">|</span> <span class="s1">&#39;*&#39;</span> <span class="p">[</span><span class="n">vfpdef</span><span class="p">]</span> <span class="p">(</span><span class="s1">&#39;,&#39;</span> <span class="n">vfpdef</span> <span class="p">[</span><span class="s1">&#39;=&#39;</span> <span class="n">test</span><span class="p">])</span><span class="o">*</span> <span class="p">[</span><span class="s1">&#39;,&#39;</span> <span class="p">[</span><span class="s1">&#39;**&#39;</span> <span class="n">vfpdef</span> <span class="p">[</span><span class="s1">&#39;,&#39;</span><span class="p">]]]</span>
  <span class="o">|</span> <span class="s1">&#39;**&#39;</span> <span class="n">vfpdef</span> <span class="p">[</span><span class="s1">&#39;,&#39;</span><span class="p">]</span>
<span class="p">)</span>
<span class="n">vfpdef</span><span class="p">:</span> <span class="n">NAME</span>

<span class="n">stmt</span><span class="p">:</span> <span class="n">simple_stmt</span> <span class="o">|</span> <span class="n">compound_stmt</span>
<span class="n">simple_stmt</span><span class="p">:</span> <span class="n">small_stmt</span> <span class="p">(</span><span class="s1">&#39;;&#39;</span> <span class="n">small_stmt</span><span class="p">)</span><span class="o">*</span> <span class="p">[</span><span class="s1">&#39;;&#39;</span><span class="p">]</span> <span class="n">NEWLINE</span>
<span class="n">small_stmt</span><span class="p">:</span> <span class="p">(</span><span class="n">expr_stmt</span> <span class="o">|</span> <span class="n">del_stmt</span> <span class="o">|</span> <span class="n">pass_stmt</span> <span class="o">|</span> <span class="n">flow_stmt</span> <span class="o">|</span>
             <span class="n">import_stmt</span> <span class="o">|</span> <span class="n">global_stmt</span> <span class="o">|</span> <span class="n">nonlocal_stmt</span> <span class="o">|</span> <span class="n">assert_stmt</span><span class="p">)</span>
<span class="n">expr_stmt</span><span class="p">:</span> <span class="n">testlist_star_expr</span> <span class="p">(</span><span class="n">annassign</span> <span class="o">|</span> <span class="n">augassign</span> <span class="p">(</span><span class="n">yield_expr</span><span class="o">|</span><span class="n">testlist</span><span class="p">)</span> <span class="o">|</span>
                     <span class="p">(</span><span class="s1">&#39;=&#39;</span> <span class="p">(</span><span class="n">yield_expr</span><span class="o">|</span><span class="n">testlist_star_expr</span><span class="p">))</span><span class="o">*</span><span class="p">)</span>
<span class="n">annassign</span><span class="p">:</span> <span class="s1">&#39;:&#39;</span> <span class="n">test</span> <span class="p">[</span><span class="s1">&#39;=&#39;</span> <span class="n">test</span><span class="p">]</span>
<span class="n">testlist_star_expr</span><span class="p">:</span> <span class="p">(</span><span class="n">test</span><span class="o">|</span><span class="n">star_expr</span><span class="p">)</span> <span class="p">(</span><span class="s1">&#39;,&#39;</span> <span class="p">(</span><span class="n">test</span><span class="o">|</span><span class="n">star_expr</span><span class="p">))</span><span class="o">*</span> <span class="p">[</span><span class="s1">&#39;,&#39;</span><span class="p">]</span>
<span class="n">augassign</span><span class="p">:</span> <span class="p">(</span><span class="s1">&#39;+=&#39;</span> <span class="o">|</span> <span class="s1">&#39;-=&#39;</span> <span class="o">|</span> <span class="s1">&#39;*=&#39;</span> <span class="o">|</span> <span class="s1">&#39;@=&#39;</span> <span class="o">|</span> <span class="s1">&#39;/=&#39;</span> <span class="o">|</span> <span class="s1">&#39;%=&#39;</span> <span class="o">|</span> <span class="s1">&#39;&amp;=&#39;</span> <span class="o">|</span> <span class="s1">&#39;|=&#39;</span> <span class="o">|</span> <span class="s1">&#39;^=&#39;</span> <span class="o">|</span>
            <span class="s1">&#39;&lt;&lt;=&#39;</span> <span class="o">|</span> <span class="s1">&#39;&gt;&gt;=&#39;</span> <span class="o">|</span> <span class="s1">&#39;**=&#39;</span> <span class="o">|</span> <span class="s1">&#39;//=&#39;</span><span class="p">)</span>
<span class="c1"># For normal and annotated assignments, additional restrictions enforced by the interpreter</span>
<span class="n">del_stmt</span><span class="p">:</span> <span class="s1">&#39;del&#39;</span> <span class="n">exprlist</span>
<span class="n">pass_stmt</span><span class="p">:</span> <span class="s1">&#39;pass&#39;</span>
<span class="n">flow_stmt</span><span class="p">:</span> <span class="n">break_stmt</span> <span class="o">|</span> <span class="n">continue_stmt</span> <span class="o">|</span> <span class="n">return_stmt</span> <span class="o">|</span> <span class="n">raise_stmt</span> <span class="o">|</span> <span class="n">yield_stmt</span>
<span class="n">break_stmt</span><span class="p">:</span> <span class="s1">&#39;break&#39;</span>
<span class="n">continue_stmt</span><span class="p">:</span> <span class="s1">&#39;continue&#39;</span>
<span class="n">return_stmt</span><span class="p">:</span> <span class="s1">&#39;return&#39;</span> <span class="p">[</span><span class="n">testlist</span><span class="p">]</span>
<span class="n">yield_stmt</span><span class="p">:</span> <span class="n">yield_expr</span>
<span class="n">raise_stmt</span><span class="p">:</span> <span class="s1">&#39;raise&#39;</span> <span class="p">[</span><span class="n">test</span> <span class="p">[</span><span class="s1">&#39;from&#39;</span> <span class="n">test</span><span class="p">]]</span>
<span class="n">import_stmt</span><span class="p">:</span> <span class="n">import_name</span> <span class="o">|</span> <span class="n">import_from</span>
<span class="n">import_name</span><span class="p">:</span> <span class="s1">&#39;import&#39;</span> <span class="n">dotted_as_names</span>
<span class="c1"># note below: the (&#39;.&#39; | &#39;...&#39;) is necessary because &#39;...&#39; is tokenized as ELLIPSIS</span>
<span class="n">import_from</span><span class="p">:</span> <span class="p">(</span><span class="s1">&#39;from&#39;</span> <span class="p">((</span><span class="s1">&#39;.&#39;</span> <span class="o">|</span> <span class="s1">&#39;...&#39;</span><span class="p">)</span><span class="o">*</span> <span class="n">dotted_name</span> <span class="o">|</span> <span class="p">(</span><span class="s1">&#39;.&#39;</span> <span class="o">|</span> <span class="s1">&#39;...&#39;</span><span class="p">)</span><span class="o">+</span><span class="p">)</span>
              <span class="s1">&#39;import&#39;</span> <span class="p">(</span><span class="s1">&#39;*&#39;</span> <span class="o">|</span> <span class="s1">&#39;(&#39;</span> <span class="n">import_as_names</span> <span class="s1">&#39;)&#39;</span> <span class="o">|</span> <span class="n">import_as_names</span><span class="p">))</span>
<span class="n">import_as_name</span><span class="p">:</span> <span class="n">NAME</span> <span class="p">[</span><span class="s1">&#39;as&#39;</span> <span class="n">NAME</span><span class="p">]</span>
<span class="n">dotted_as_name</span><span class="p">:</span> <span class="n">dotted_name</span> <span class="p">[</span><span class="s1">&#39;as&#39;</span> <span class="n">NAME</span><span class="p">]</span>
<span class="n">import_as_names</span><span class="p">:</span> <span class="n">import_as_name</span> <span class="p">(</span><span class="s1">&#39;,&#39;</span> <span class="n">import_as_name</span><span class="p">)</span><span class="o">*</span> <span class="p">[</span><span class="s1">&#39;,&#39;</span><span class="p">]</span>
<span class="n">dotted_as_names</span><span class="p">:</span> <span class="n">dotted_as_name</span> <span class="p">(</span><span class="s1">&#39;,&#39;</span> <span class="n">dotted_as_name</span><span class="p">)</span><span class="o">*</span>
<span class="n">dotted_name</span><span class="p">:</span> <span class="n">NAME</span> <span class="p">(</span><span class="s1">&#39;.&#39;</span> <span class="n">NAME</span><span class="p">)</span><span class="o">*</span>
<span class="n">global_stmt</span><span class="p">:</span> <span class="s1">&#39;global&#39;</span> <span class="n">NAME</span> <span class="p">(</span><span class="s1">&#39;,&#39;</span> <span class="n">NAME</span><span class="p">)</span><span class="o">*</span>
<span class="n">nonlocal_stmt</span><span class="p">:</span> <span class="s1">&#39;nonlocal&#39;</span> <span class="n">NAME</span> <span class="p">(</span><span class="s1">&#39;,&#39;</span> <span class="n">NAME</span><span class="p">)</span><span class="o">*</span>
<span class="n">assert_stmt</span><span class="p">:</span> <span class="s1">&#39;assert&#39;</span> <span class="n">test</span> <span class="p">[</span><span class="s1">&#39;,&#39;</span> <span class="n">test</span><span class="p">]</span>

<span class="n">compound_stmt</span><span class="p">:</span> <span class="n">if_stmt</span> <span class="o">|</span> <span class="n">while_stmt</span> <span class="o">|</span> <span class="n">for_stmt</span> <span class="o">|</span> <span class="n">try_stmt</span> <span class="o">|</span> <span class="n">with_stmt</span> <span class="o">|</span> <span class="n">funcdef</span> <span class="o">|</span> <span class="n">classdef</span> <span class="o">|</span> <span class="n">decorated</span> <span class="o">|</span> <span class="n">async_stmt</span>
<span class="n">async_stmt</span><span class="p">:</span> <span class="s1">&#39;async&#39;</span> <span class="p">(</span><span class="n">funcdef</span> <span class="o">|</span> <span class="n">with_stmt</span> <span class="o">|</span> <span class="n">for_stmt</span><span class="p">)</span>
<span class="n">if_stmt</span><span class="p">:</span> <span class="s1">&#39;if&#39;</span> <span class="n">test</span> <span class="s1">&#39;:&#39;</span> <span class="n">suite</span> <span class="p">(</span><span class="s1">&#39;elif&#39;</span> <span class="n">test</span> <span class="s1">&#39;:&#39;</span> <span class="n">suite</span><span class="p">)</span><span class="o">*</span> <span class="p">[</span><span class="s1">&#39;else&#39;</span> <span class="s1">&#39;:&#39;</span> <span class="n">suite</span><span class="p">]</span>
<span class="n">while_stmt</span><span class="p">:</span> <span class="s1">&#39;while&#39;</span> <span class="n">test</span> <span class="s1">&#39;:&#39;</span> <span class="n">suite</span> <span class="p">[</span><span class="s1">&#39;else&#39;</span> <span class="s1">&#39;:&#39;</span> <span class="n">suite</span><span class="p">]</span>
<span class="n">for_stmt</span><span class="p">:</span> <span class="s1">&#39;for&#39;</span> <span class="n">exprlist</span> <span class="s1">&#39;in&#39;</span> <span class="n">testlist</span> <span class="s1">&#39;:&#39;</span> <span class="n">suite</span> <span class="p">[</span><span class="s1">&#39;else&#39;</span> <span class="s1">&#39;:&#39;</span> <span class="n">suite</span><span class="p">]</span>
<span class="n">try_stmt</span><span class="p">:</span> <span class="p">(</span><span class="s1">&#39;try&#39;</span> <span class="s1">&#39;:&#39;</span> <span class="n">suite</span>
           <span class="p">((</span><span class="n">except_clause</span> <span class="s1">&#39;:&#39;</span> <span class="n">suite</span><span class="p">)</span><span class="o">+</span>
            <span class="p">[</span><span class="s1">&#39;else&#39;</span> <span class="s1">&#39;:&#39;</span> <span class="n">suite</span><span class="p">]</span>
            <span class="p">[</span><span class="s1">&#39;finally&#39;</span> <span class="s1">&#39;:&#39;</span> <span class="n">suite</span><span class="p">]</span> <span class="o">|</span>
           <span class="s1">&#39;finally&#39;</span> <span class="s1">&#39;:&#39;</span> <span class="n">suite</span><span class="p">))</span>
<span class="n">with_stmt</span><span class="p">:</span> <span class="s1">&#39;with&#39;</span> <span class="n">with_item</span> <span class="p">(</span><span class="s1">&#39;,&#39;</span> <span class="n">with_item</span><span class="p">)</span><span class="o">*</span>  <span class="s1">&#39;:&#39;</span> <span class="n">suite</span>
<span class="n">with_item</span><span class="p">:</span> <span class="n">test</span> <span class="p">[</span><span class="s1">&#39;as&#39;</span> <span class="n">expr</span><span class="p">]</span>
<span class="c1"># NB compile.c makes sure that the default except clause is last</span>
<span class="n">except_clause</span><span class="p">:</span> <span class="s1">&#39;except&#39;</span> <span class="p">[</span><span class="n">test</span> <span class="p">[</span><span class="s1">&#39;as&#39;</span> <span class="n">NAME</span><span class="p">]]</span>
<span class="n">suite</span><span class="p">:</span> <span class="n">simple_stmt</span> <span class="o">|</span> <span class="n">NEWLINE</span> <span class="n">INDENT</span> <span class="n">stmt</span><span class="o">+</span> <span class="n">DEDENT</span>

<span class="n">test</span><span class="p">:</span> <span class="n">or_test</span> <span class="p">[</span><span class="s1">&#39;if&#39;</span> <span class="n">or_test</span> <span class="s1">&#39;else&#39;</span> <span class="n">test</span><span class="p">]</span> <span class="o">|</span> <span class="n">lambdef</span>
<span class="n">test_nocond</span><span class="p">:</span> <span class="n">or_test</span> <span class="o">|</span> <span class="n">lambdef_nocond</span>
<span class="n">lambdef</span><span class="p">:</span> <span class="s1">&#39;lambda&#39;</span> <span class="p">[</span><span class="n">varargslist</span><span class="p">]</span> <span class="s1">&#39;:&#39;</span> <span class="n">test</span>
<span class="n">lambdef_nocond</span><span class="p">:</span> <span class="s1">&#39;lambda&#39;</span> <span class="p">[</span><span class="n">varargslist</span><span class="p">]</span> <span class="s1">&#39;:&#39;</span> <span class="n">test_nocond</span>
<span class="n">or_test</span><span class="p">:</span> <span class="n">and_test</span> <span class="p">(</span><span class="s1">&#39;or&#39;</span> <span class="n">and_test</span><span class="p">)</span><span class="o">*</span>
<span class="n">and_test</span><span class="p">:</span> <span class="n">not_test</span> <span class="p">(</span><span class="s1">&#39;and&#39;</span> <span class="n">not_test</span><span class="p">)</span><span class="o">*</span>
<span class="n">not_test</span><span class="p">:</span> <span class="s1">&#39;not&#39;</span> <span class="n">not_test</span> <span class="o">|</span> <span class="n">comparison</span>
<span class="n">comparison</span><span class="p">:</span> <span class="n">expr</span> <span class="p">(</span><span class="n">comp_op</span> <span class="n">expr</span><span class="p">)</span><span class="o">*</span>
<span class="c1"># &lt;&gt; isn&#39;t actually a valid comparison operator in Python. It&#39;s here for the</span>
<span class="c1"># sake of a __future__ import described in PEP 401 (which really works :-)</span>
<span class="n">comp_op</span><span class="p">:</span> <span class="s1">&#39;&lt;&#39;</span><span class="o">|</span><span class="s1">&#39;&gt;&#39;</span><span class="o">|</span><span class="s1">&#39;==&#39;</span><span class="o">|</span><span class="s1">&#39;&gt;=&#39;</span><span class="o">|</span><span class="s1">&#39;&lt;=&#39;</span><span class="o">|</span><span class="s1">&#39;&lt;&gt;&#39;</span><span class="o">|</span><span class="s1">&#39;!=&#39;</span><span class="o">|</span><span class="s1">&#39;in&#39;</span><span class="o">|</span><span class="s1">&#39;not&#39;</span> <span class="s1">&#39;in&#39;</span><span class="o">|</span><span class="s1">&#39;is&#39;</span><span class="o">|</span><span class="s1">&#39;is&#39;</span> <span class="s1">&#39;not&#39;</span>
<span class="n">star_expr</span><span class="p">:</span> <span class="s1">&#39;*&#39;</span> <span class="n">expr</span>
<span class="n">expr</span><span class="p">:</span> <span class="n">xor_expr</span> <span class="p">(</span><span class="s1">&#39;|&#39;</span> <span class="n">xor_expr</span><span class="p">)</span><span class="o">*</span>
<span class="n">xor_expr</span><span class="p">:</span> <span class="n">and_expr</span> <span class="p">(</span><span class="s1">&#39;^&#39;</span> <span class="n">and_expr</span><span class="p">)</span><span class="o">*</span>
<span class="n">and_expr</span><span class="p">:</span> <span class="n">shift_expr</span> <span class="p">(</span><span class="s1">&#39;&amp;&#39;</span> <span class="n">shift_expr</span><span class="p">)</span><span class="o">*</span>
<span class="n">shift_expr</span><span class="p">:</span> <span class="n">arith_expr</span> <span class="p">((</span><span class="s1">&#39;&lt;&lt;&#39;</span><span class="o">|</span><span class="s1">&#39;&gt;&gt;&#39;</span><span class="p">)</span> <span class="n">arith_expr</span><span class="p">)</span><span class="o">*</span>
<span class="n">arith_expr</span><span class="p">:</span> <span class="n">term</span> <span class="p">((</span><span class="s1">&#39;+&#39;</span><span class="o">|</span><span class="s1">&#39;-&#39;</span><span class="p">)</span> <span class="n">term</span><span class="p">)</span><span class="o">*</span>
<span class="n">term</span><span class="p">:</span> <span class="n">factor</span> <span class="p">((</span><span class="s1">&#39;*&#39;</span><span class="o">|</span><span class="s1">&#39;@&#39;</span><span class="o">|</span><span class="s1">&#39;/&#39;</span><span class="o">|</span><span class="s1">&#39;%&#39;</span><span class="o">|</span><span class="s1">&#39;//&#39;</span><span class="p">)</span> <span class="n">factor</span><span class="p">)</span><span class="o">*</span>
<span class="n">factor</span><span class="p">:</span> <span class="p">(</span><span class="s1">&#39;+&#39;</span><span class="o">|</span><span class="s1">&#39;-&#39;</span><span class="o">|</span><span class="s1">&#39;~&#39;</span><span class="p">)</span> <span class="n">factor</span> <span class="o">|</span> <span class="n">power</span>
<span class="n">power</span><span class="p">:</span> <span class="n">atom_expr</span> <span class="p">[</span><span class="s1">&#39;**&#39;</span> <span class="n">factor</span><span class="p">]</span>
<span class="n">atom_expr</span><span class="p">:</span> <span class="p">[</span><span class="s1">&#39;await&#39;</span><span class="p">]</span> <span class="n">atom</span> <span class="n">trailer</span><span class="o">*</span>
<span class="n">atom</span><span class="p">:</span> <span class="p">(</span><span class="s1">&#39;(&#39;</span> <span class="p">[</span><span class="n">yield_expr</span><span class="o">|</span><span class="n">testlist_comp</span><span class="p">]</span> <span class="s1">&#39;)&#39;</span> <span class="o">|</span>
       <span class="s1">&#39;[&#39;</span> <span class="p">[</span><span class="n">testlist_comp</span><span class="p">]</span> <span class="s1">&#39;]&#39;</span> <span class="o">|</span>
       <span class="s1">&#39;{&#39;</span> <span class="p">[</span><span class="n">dictorsetmaker</span><span class="p">]</span> <span class="s1">&#39;}&#39;</span> <span class="o">|</span>
       <span class="n">NAME</span> <span class="o">|</span> <span class="n">NUMBER</span> <span class="o">|</span> <span class="n">STRING</span><span class="o">+</span> <span class="o">|</span> <span class="s1">&#39;...&#39;</span> <span class="o">|</span> <span class="s1">&#39;None&#39;</span> <span class="o">|</span> <span class="s1">&#39;True&#39;</span> <span class="o">|</span> <span class="s1">&#39;False&#39;</span><span class="p">)</span>
<span class="n">testlist_comp</span><span class="p">:</span> <span class="p">(</span><span class="n">test</span><span class="o">|</span><span class="n">star_expr</span><span class="p">)</span> <span class="p">(</span> <span class="n">comp_for</span> <span class="o">|</span> <span class="p">(</span><span class="s1">&#39;,&#39;</span> <span class="p">(</span><span class="n">test</span><span class="o">|</span><span class="n">star_expr</span><span class="p">))</span><span class="o">*</span> <span class="p">[</span><span class="s1">&#39;,&#39;</span><span class="p">]</span> <span class="p">)</span>
<span class="n">trailer</span><span class="p">:</span> <span class="s1">&#39;(&#39;</span> <span class="p">[</span><span class="n">arglist</span><span class="p">]</span> <span class="s1">&#39;)&#39;</span> <span class="o">|</span> <span class="s1">&#39;[&#39;</span> <span class="n">subscriptlist</span> <span class="s1">&#39;]&#39;</span> <span class="o">|</span> <span class="s1">&#39;.&#39;</span> <span class="n">NAME</span>
<span class="n">subscriptlist</span><span class="p">:</span> <span class="n">subscript</span> <span class="p">(</span><span class="s1">&#39;,&#39;</span> <span class="n">subscript</span><span class="p">)</span><span class="o">*</span> <span class="p">[</span><span class="s1">&#39;,&#39;</span><span class="p">]</span>
<span class="n">subscript</span><span class="p">:</span> <span class="n">test</span> <span class="o">|</span> <span class="p">[</span><span class="n">test</span><span class="p">]</span> <span class="s1">&#39;:&#39;</span> <span class="p">[</span><span class="n">test</span><span class="p">]</span> <span class="p">[</span><span class="n">sliceop</span><span class="p">]</span>
<span class="n">sliceop</span><span class="p">:</span> <span class="s1">&#39;:&#39;</span> <span class="p">[</span><span class="n">test</span><span class="p">]</span>
<span class="n">exprlist</span><span class="p">:</span> <span class="p">(</span><span class="n">expr</span><span class="o">|</span><span class="n">star_expr</span><span class="p">)</span> <span class="p">(</span><span class="s1">&#39;,&#39;</span> <span class="p">(</span><span class="n">expr</span><span class="o">|</span><span class="n">star_expr</span><span class="p">))</span><span class="o">*</span> <span class="p">[</span><span class="s1">&#39;,&#39;</span><span class="p">]</span>
<span class="n">testlist</span><span class="p">:</span> <span class="n">test</span> <span class="p">(</span><span class="s1">&#39;,&#39;</span> <span class="n">test</span><span class="p">)</span><span class="o">*</span> <span class="p">[</span><span class="s1">&#39;,&#39;</span><span class="p">]</span>
<span class="n">dictorsetmaker</span><span class="p">:</span> <span class="p">(</span> <span class="p">((</span><span class="n">test</span> <span class="s1">&#39;:&#39;</span> <span class="n">test</span> <span class="o">|</span> <span class="s1">&#39;**&#39;</span> <span class="n">expr</span><span class="p">)</span>
                   <span class="p">(</span><span class="n">comp_for</span> <span class="o">|</span> <span class="p">(</span><span class="s1">&#39;,&#39;</span> <span class="p">(</span><span class="n">test</span> <span class="s1">&#39;:&#39;</span> <span class="n">test</span> <span class="o">|</span> <span class="s1">&#39;**&#39;</span> <span class="n">expr</span><span class="p">))</span><span class="o">*</span> <span class="p">[</span><span class="s1">&#39;,&#39;</span><span class="p">]))</span> <span class="o">|</span>
                  <span class="p">((</span><span class="n">test</span> <span class="o">|</span> <span class="n">star_expr</span><span class="p">)</span>
                   <span class="p">(</span><span class="n">comp_for</span> <span class="o">|</span> <span class="p">(</span><span class="s1">&#39;,&#39;</span> <span class="p">(</span><span class="n">test</span> <span class="o">|</span> <span class="n">star_expr</span><span class="p">))</span><span class="o">*</span> <span class="p">[</span><span class="s1">&#39;,&#39;</span><span class="p">]))</span> <span class="p">)</span>

<span class="n">classdef</span><span class="p">:</span> <span class="s1">&#39;class&#39;</span> <span class="n">NAME</span> <span class="p">[</span><span class="s1">&#39;(&#39;</span> <span class="p">[</span><span class="n">arglist</span><span class="p">]</span> <span class="s1">&#39;)&#39;</span><span class="p">]</span> <span class="s1">&#39;:&#39;</span> <span class="n">suite</span>

<span class="n">arglist</span><span class="p">:</span> <span class="n">argument</span> <span class="p">(</span><span class="s1">&#39;,&#39;</span> <span class="n">argument</span><span class="p">)</span><span class="o">*</span>  <span class="p">[</span><span class="s1">&#39;,&#39;</span><span class="p">]</span>

<span class="c1"># The reason that keywords are test nodes instead of NAME is that using NAME</span>
<span class="c1"># results in an ambiguity. ast.c makes sure it&#39;s a NAME.</span>
<span class="c1"># &quot;test &#39;=&#39; test&quot; is really &quot;keyword &#39;=&#39; test&quot;, but we have no such token.</span>
<span class="c1"># These need to be in a single rule to avoid grammar that is ambiguous</span>
<span class="c1"># to our LL(1) parser. Even though &#39;test&#39; includes &#39;*expr&#39; in star_expr,</span>
<span class="c1"># we explicitly match &#39;*&#39; here, too, to give it proper precedence.</span>
<span class="c1"># Illegal combinations and orderings are blocked in ast.c:</span>
<span class="c1"># multiple (test comp_for) arguments are blocked; keyword unpackings</span>
<span class="c1"># that precede iterable unpackings are blocked; etc.</span>
<span class="n">argument</span><span class="p">:</span> <span class="p">(</span> <span class="n">test</span> <span class="p">[</span><span class="n">comp_for</span><span class="p">]</span> <span class="o">|</span>
            <span class="n">test</span> <span class="s1">&#39;=&#39;</span> <span class="n">test</span> <span class="o">|</span>
            <span class="s1">&#39;**&#39;</span> <span class="n">test</span> <span class="o">|</span>
            <span class="s1">&#39;*&#39;</span> <span class="n">test</span> <span class="p">)</span>

<span class="n">comp_iter</span><span class="p">:</span> <span class="n">comp_for</span> <span class="o">|</span> <span class="n">comp_if</span>
<span class="n">sync_comp_for</span><span class="p">:</span> <span class="s1">&#39;for&#39;</span> <span class="n">exprlist</span> <span class="s1">&#39;in&#39;</span> <span class="n">or_test</span> <span class="p">[</span><span class="n">comp_iter</span><span class="p">]</span>
<span class="n">comp_for</span><span class="p">:</span> <span class="p">[</span><span class="s1">&#39;async&#39;</span><span class="p">]</span> <span class="n">sync_comp_for</span>
<span class="n">comp_if</span><span class="p">:</span> <span class="s1">&#39;if&#39;</span> <span class="n">test_nocond</span> <span class="p">[</span><span class="n">comp_iter</span><span class="p">]</span>

<span class="c1"># not used in grammar, but may appear in &quot;node&quot; passed from Parser to Compiler</span>
<span class="n">encoding_decl</span><span class="p">:</span> <span class="n">NAME</span>

<span class="n">yield_expr</span><span class="p">:</span> <span class="s1">&#39;yield&#39;</span> <span class="p">[</span><span class="n">yield_arg</span><span class="p">]</span>
<span class="n">yield_arg</span><span class="p">:</span> <span class="s1">&#39;from&#39;</span> <span class="n">test</span> <span class="o">|</span> <span class="n">testlist</span>
</pre></div>


<p>现在你已经能读懂 BNF 了，那么，可以再读读用 BNF 描述的 Regex 语法<a href='#fn2' name='fn2b'><sup>[2]</sup></a>，就当复习了 —— 很短的：</p>
<div class="highlight"><pre><span></span>BNF grammar for Perl-style regular expressions

<span class="p">&lt;</span><span class="nt">RE</span><span class="p">&gt;</span>             ::=  <span class="p">&lt;</span><span class="nt">union</span><span class="p">&gt;</span> | <span class="p">&lt;</span><span class="nt">simple-RE</span><span class="p">&gt;</span>
<span class="p">&lt;</span><span class="nt">union</span><span class="p">&gt;</span>          ::=  <span class="p">&lt;</span><span class="nt">RE</span><span class="p">&gt;</span> &quot;|&quot; <span class="p">&lt;</span><span class="nt">simple-RE</span><span class="p">&gt;</span>
<span class="p">&lt;</span><span class="nt">simple-RE</span><span class="p">&gt;</span>      ::=  <span class="p">&lt;</span><span class="nt">concatenation</span><span class="p">&gt;</span> | <span class="p">&lt;</span><span class="nt">basic-RE</span><span class="p">&gt;</span>
<span class="p">&lt;</span><span class="nt">concatenation</span><span class="p">&gt;</span>  ::=  <span class="p">&lt;</span><span class="nt">simple-RE</span><span class="p">&gt;</span> <span class="p">&lt;</span><span class="nt">basic-RE</span><span class="p">&gt;</span>
<span class="p">&lt;</span><span class="nt">basic-RE</span><span class="p">&gt;</span>       ::=  <span class="p">&lt;</span><span class="nt">star</span><span class="p">&gt;</span> | <span class="p">&lt;</span><span class="nt">plus</span><span class="p">&gt;</span> | <span class="p">&lt;</span><span class="nt">elementary-RE</span><span class="p">&gt;</span>
<span class="p">&lt;</span><span class="nt">star</span><span class="p">&gt;</span>           ::=  <span class="p">&lt;</span><span class="nt">elementary-RE</span><span class="p">&gt;</span> &quot;*&quot;
<span class="p">&lt;</span><span class="nt">plus</span><span class="p">&gt;</span>           ::=  <span class="p">&lt;</span><span class="nt">elementary-RE</span><span class="p">&gt;</span> &quot;+&quot;
<span class="p">&lt;</span><span class="nt">elementary-RE</span><span class="p">&gt;</span>  ::=  <span class="p">&lt;</span><span class="nt">group</span><span class="p">&gt;</span> | <span class="p">&lt;</span><span class="nt">any</span><span class="p">&gt;</span> | <span class="p">&lt;</span><span class="nt">eos</span><span class="p">&gt;</span> | <span class="p">&lt;</span><span class="nt">char</span><span class="p">&gt;</span> | <span class="p">&lt;</span><span class="nt">set</span><span class="p">&gt;</span>
<span class="p">&lt;</span><span class="nt">group</span><span class="p">&gt;</span>          ::=  &quot;(&quot; <span class="p">&lt;</span><span class="nt">RE</span><span class="p">&gt;</span> &quot;)&quot;
<span class="p">&lt;</span><span class="nt">any</span><span class="p">&gt;</span>            ::=  &quot;.&quot;
<span class="p">&lt;</span><span class="nt">eos</span><span class="p">&gt;</span>            ::=  &quot;$&quot;
<span class="p">&lt;</span><span class="nt">char</span><span class="p">&gt;</span>           ::=  any non metacharacter | &quot;\&quot; metacharacter
<span class="p">&lt;</span><span class="nt">set</span><span class="p">&gt;</span>            ::=  <span class="p">&lt;</span><span class="nt">positive-set</span><span class="p">&gt;</span> | <span class="p">&lt;</span><span class="nt">negative-set</span><span class="p">&gt;</span>
<span class="p">&lt;</span><span class="nt">positive-set</span><span class="p">&gt;</span>   ::=  &quot;[&quot; <span class="p">&lt;</span><span class="nt">set-items</span><span class="p">&gt;</span> &quot;]&quot;
<span class="p">&lt;</span><span class="nt">negative-set</span><span class="p">&gt;</span>   ::=  &quot;[^&quot; <span class="p">&lt;</span><span class="nt">set-items</span><span class="p">&gt;</span> &quot;]&quot;
<span class="p">&lt;</span><span class="nt">set-items</span><span class="p">&gt;</span>      ::=  <span class="p">&lt;</span><span class="nt">set-item</span><span class="p">&gt;</span> | <span class="p">&lt;</span><span class="nt">set-item</span><span class="p">&gt;</span> <span class="p">&lt;</span><span class="nt">set-items</span><span class="p">&gt;</span>
<span class="p">&lt;</span><span class="nt">set-item</span><span class="p">&gt;</span>       ::=  <span class="p">&lt;</span><span class="nt">range</span><span class="p">&gt;</span> | <span class="p">&lt;</span><span class="nt">char</span><span class="p">&gt;</span>
<span class="p">&lt;</span><span class="nt">range</span><span class="p">&gt;</span>          ::=  <span class="p">&lt;</span><span class="nt">char</span><span class="p">&gt;</span> &quot;-&quot; <span class="p">&lt;</span><span class="nt">char</span><span class="p">&gt;</span>
</pre></div>


<p>真的没原来以为得那么神秘，是不？<a href='#fn3' name='fn3b'><sup>[3]</sup></a></p>
<p>都学到这儿了…… 顺带再自学个东西吧。</p>
<p>这个东西叫 <code>glob</code>，是 Global 的缩写。你可以把它理解为 “超级简化版正则表达式” —— 它最初是 Unix/Posix 操作系统中用来匹配文件名的 “通配符”。</p>
<p>先看一张 1971 的 Unix 操作系统中关于 glob 的截图：
<img alt="123" src="https://raw.githubusercontent.com/selfteaching/the-craft-of-selfteaching/master/images/Unix_Glob_Reference.png?raw=true"></p>
<blockquote>
<p>A screenshot of the original 1971 Unix reference page for glob – note the owner is dmr, short for Dennis Ritchie.</p>
</blockquote>
<p>glob 的主要符号只有这么几个：</p>
<blockquote>
<ul>
<li><code>*</code></li>
<li><code>?</code></li>
<li><code>[abc]</code></li>
<li><code>[^abc]</code></li>
</ul>
</blockquote>
<p>现在的你，打开 Wikipedia 上的关于 glob 和 Wildcard character 的页面，肯定能做到 “无障碍” 理解：</p>
<blockquote>
<ul>
<li>https://en.wikipedia.org/wiki/Glob_(programming)</li>
<li>https://en.wikipedia.org/wiki/Wildcard_character</li>
</ul>
</blockquote>
<p>顺带说，现在你再去读关于 Format String 的官方文档，就不会再觉得 “根本看不懂” 了，恰恰相反，你会觉得 “我怎么之前连这个都看不懂呢？”</p>
<blockquote>
<p>https://docs.python.org/3/library/string.html#format-string-syntax</p>
</blockquote>
<p>在自学这件事上，失败者的死法看起来千变万化，但其实都是一样的…… 只不过是因为怕麻烦或者基础知识不够而不去读最重要的文档。</p>
<p>比如，学英语的时候死活不读语法书。其实英文语法书也没多难啊？再厚，不也是用来 “查” 的吗？不就是多记几个标记就可以读懂的吗？比如，词性标记，<code>v.</code>, <code>n.</code>, <code>adj.</code>, <code>adv.</code>, <code>prep.</code>... 不就是相当于地图上的图例吗？那语法书，和现在这里提到的官方文档，不都是 “自学者地图” 吗？</p>
<p>但就是这么一点点简单的东西，挡住了几乎所有人，真是可怕。</p>
<hr>
<p><strong>脚注</strong></p>
<p><a name='fn1'>[1]</a>：<a href="https://docs.python.org/3/reference/introduction.html#notation">The Python Language Reference » 1.2 Notation</a> —— 这个链接必须去看一看……</p>
<p><a href='#fn1b'><small>↑Back to Content↑</small></a></p>
<p><a name='fn2'>[2]</a>：<a href="http://www.cs.sfu.ca/~cameron/Teaching/384/99-3/regexp-plg.html">Perl Style Regular Expressions in Prolog</a> CMPT 384 Lecture Notes
Robert D. Cameron November 29 - December 1, 1999</p>
<p><a href='#fn2b'><small>↑Back to Content↑</small></a></p>
<p><a name='fn3'>[3]</a>：很少有人注意到：在很多编程语言的文法文档中，<code>"$"</code> 被称为 <code>&lt;eos&gt;</code> —— 2017 年 5 月我投资了一个初创公司，听说他们的资产名称叫做 <code>eos</code>…… 我当场就被这个梗逗乐了。</p>
<p><a href='#fn3b'><small>↑Back to Content↑</small></a></p>
    </div><!-- /.entry-content -->

  </article>
</section>
        <section id="extras" class="body">
                <div class="blogroll">
                        <h2>blogroll</h2>
                        <ul>
                            <li><a href="http://getpelican.com/">Pelican</a></li>
                            <li><a href="http://python.org/">Python.org</a></li>
                            <li><a href="http://jinja.pocoo.org/">Jinja2</a></li>
                            <li><a href="#">You can modify those links in your config file</a></li>
                        </ul>
                </div><!-- /.blogroll -->
                <div class="social">
                        <h2>social</h2>
                        <ul>

                            <li><a href="#">You can add links in your config file</a></li>
                            <li><a href="#">Another social link</a></li>
                        </ul>
                </div><!-- /.social -->
        </section><!-- /#extras -->

        <footer id="contentinfo" class="body">
                <p>Powered by <a href="http://www.maxiaoan.com/">Maxiaoan</a></p>
        </footer><!-- /#contentinfo -->

</body>
</html>